package ofdinv

import (
	"archive/zip"
	"encoding/xml"
	"errors"
	"fmt"
	"io"
	"os"
	"slices"
	"strings"

	"path/filepath"
)

var businessSlice []string

func init() {
	businessSlice = []string{"货物运输服务", "成品油"}
}

// OFDReader 表示OFD文件阅读器
type OFDReader struct {
	zipReader *zip.Reader
	file      *os.File
	tempDir   string
	filePath  string // 保存原始文件路径
}

// NewOFDReader 创建新的OFD阅读器
func NewOFDReader(filePath string) (*OFDReader, error) {
	file, err := os.Open(filePath)
	if err != nil {
		return nil, fmt.Errorf("打开OFD文件失败: %v", err)
	}

	fileInfo, err := file.Stat()
	if err != nil {
		file.Close()
		return nil, fmt.Errorf("获取文件信息失败: %v", err)
	}

	zipReader, err := zip.NewReader(file, fileInfo.Size())
	if err != nil {
		file.Close()
		return nil, fmt.Errorf("创建ZIP阅读器失败: %v", err)
	}

	// 创建临时目录用于解压文件
	tempDir, err := os.MkdirTemp("", "ofd_reader")
	if err != nil {
		file.Close()
		return nil, fmt.Errorf("创建临时目录失败: %v", err)
	}

	// 解压所有文件到临时目录
	for _, zipFile := range zipReader.File {
		err := extractZipFile(zipFile, tempDir)
		if err != nil {
			os.RemoveAll(tempDir)
			file.Close()
			return nil, fmt.Errorf("解压文件失败: %v", err)
		}
	}

	return &OFDReader{
		zipReader: zipReader,
		file:      file,
		tempDir:   tempDir,
		filePath:  filePath,
	}, nil
}

// Close 关闭OFD阅读器并清理临时文件
func (r *OFDReader) Close() error {
	if r.file != nil {
		r.file.Close()
	}
	if r.tempDir != "" {
		os.RemoveAll(r.tempDir)
	}
	return nil
}

// GetTempDir 获取临时目录路径
func (r *OFDReader) GetTempDir() string {
	return r.tempDir
}
func (r *OFDReader) ParseDocument() (*Document, error) {
	var document Document
	err := r.ReadXMLFile("Doc_0/Document.xml", &document)
	if err != nil {
		return nil, fmt.Errorf("读取Document.xml失败: %v", err)
	}
	return &document, nil
}

// 根据TypeID获取CustomTag.xml的路径
func (r *OFDReader) GetCustomTagFileLoc(typeID string) (string, error) {
	doc, err := r.ParseDocument()
	if err != nil {
		return "", fmt.Errorf("解析Document.xml失败: %v", err)
	}
	var customTagsRoot CustomTagsRoot
	CustomTagsPath := filepath.Join("Doc_0", doc.CustomTags)
	err = r.ReadXMLFile(CustomTagsPath, &customTagsRoot)
	if err != nil {
		return "", fmt.Errorf("读取CustomTag.xml失败: %v", err)
	}
	for _, root := range customTagsRoot.CustomTag {
		if root.TypeID == typeID {
			return filepath.Join("Doc_0", "Tags", root.FileLoc), nil
		}
	}
	return "", errors.New("获取CustomTag.xml路径失败")
}

func (r *OFDReader) ParseCustomTagTransport(doc *Document) (*CustomTagTransportRoot, error) {
	var customTagRoot CustomTagTransportRoot
	rootPath, err := r.GetCustomTagFileLoc("root")
	if err != nil {
		return nil, fmt.Errorf("获取CustomTag.xml路径失败: %v", err)
	}
	err = r.ReadXMLFile(rootPath, &customTagRoot)
	if err != nil {
		return nil, fmt.Errorf("读取CustomTag.xml失败: %v", err)
	}
	return &customTagRoot, nil
}

func (r *OFDReader) ParseCustomTag(doc *Document) (*CustomTagRoot, error) {
	var customTagRoot CustomTagRoot
	rootPath, err := r.GetCustomTagFileLoc("root")
	if err != nil {
		return nil, fmt.Errorf("获取CustomTag.xml路径失败: %v", err)
	}
	err = r.ReadXMLFile(rootPath, &customTagRoot)
	if err != nil {
		return nil, fmt.Errorf("读取CustomTag.xml失败: %v", err)
	}
	return &customTagRoot, nil
}

// ReadXMLFile 读取XML文件并解析到指定结构
func (r *OFDReader) ReadXMLFile(filePath string, target interface{}) error {
	fullPath := filepath.Join(r.tempDir, filePath)
	xmlFile, err := os.Open(fullPath)
	if err != nil {
		return fmt.Errorf("打开XML文件失败: %v", err)
	}
	defer xmlFile.Close()

	// 使用现有的XML解码器
	decoder := xml.NewDecoder(xmlFile)
	err = decoder.Decode(target)
	if err != nil {
		return fmt.Errorf("解析XML文件失败: %v", err)
	}

	return nil
}

// ReadFileContent 读取文件内容
func (r *OFDReader) ReadFileContent(filePath string) (string, error) {
	fullPath := filepath.Join(r.tempDir, filePath)
	content, err := os.ReadFile(fullPath)
	if err != nil {
		return "", fmt.Errorf("读取文件内容失败: %v", err)
	}
	return string(content), nil
}

func (r *OFDReader) GetINVType() (string, string, error) {
	var errStr string
	tplPath := filepath.Join("Doc_0", "Tpls", "Tpl_0", "Content.xml")
	var tplPageContent TplPageContent
	if err := r.ReadXMLFile(tplPath, &tplPageContent); err != nil {
		return "", "", fmt.Errorf("读取模板文件失败: %v", err)
	}
	invTypeStr, errTpl := tplPageContent.GetMinimumIDTextObject()
	if errTpl != nil {
		errStr = "获取发票类型错误：" + errTpl.Error()
	} else if !strings.Contains(invTypeStr, "发票") {
		errStr = "获取发票类型错误：" + invTypeStr
		invTypeStr = ""
	}
	pagePath := filepath.Join("Doc_0", "Pages", "Page_0", "Content.xml")
	var pageContent Page
	if err := r.ReadXMLFile(pagePath, &pageContent); err != nil {
		return "", "", fmt.Errorf("读取页面文件失败: %v", err)
	}
	businessType, errPage := pageContent.GetMinimumIDTextObject()
	if errPage != nil {
		errStr += ",  获取特定业务类型错误：" + errPage.Error()
	}
	if !slices.Contains(businessSlice, businessType) {
		businessType = "普通业务"
	}
	if errStr == "" {
		return invTypeStr, businessType, nil
	}
	return invTypeStr, businessType, errors.New(errStr)
}

// extractZipFile 解压单个ZIP文件
func extractZipFile(zipFile *zip.File, destDir string) error {
	// 构建目标文件路径
	targetPath := filepath.Join(destDir, zipFile.Name)

	// 创建目录
	if zipFile.FileInfo().IsDir() {
		return os.MkdirAll(targetPath, 0755)
	}

	// 创建文件所在目录
	if err := os.MkdirAll(filepath.Dir(targetPath), 0755); err != nil {
		return err
	}

	// 打开ZIP文件
	rc, err := zipFile.Open()
	if err != nil {
		return err
	}
	defer rc.Close()

	// 创建目标文件
	targetFile, err := os.OpenFile(targetPath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer targetFile.Close()

	// 复制文件内容
	_, err = io.Copy(targetFile, rc)
	if err != nil {
		return err
	}

	return nil
}
